home *** CD-ROM | disk | FTP | other *** search
/ Chip 2005 August (Alt) / CHIP 2005-08.1.iso / program / guvenlik / syslinux-3.07.exe / mkdiskimage.in < prev    next >
Encoding:
Text File  |  2004-12-30  |  5.9 KB  |  264 lines

  1. #!/usr/bin/perl
  2. ## -----------------------------------------------------------------------
  3. ##  $Id: mkdiskimage.in,v 1.14 2004/12/30 23:41:01 hpa Exp $
  4. ##   
  5. ##   Copyright 2002-2004 H. Peter Anvin - All Rights Reserved
  6. ##
  7. ##   This program is free software; you can redistribute it and/or modify
  8. ##   it under the terms of the GNU General Public License as published by
  9. ##   the Free Software Foundation, Inc., 53 Temple Place Ste 330,
  10. ##   Boston MA 02111-1307, USA; either version 2 of the License, or
  11. ##   (at your option) any later version; incorporated herein by reference.
  12. ##
  13. ## -----------------------------------------------------------------------
  14.  
  15. #
  16. # Creates a blank MS-DOS formatted hard disk image
  17. #
  18.  
  19. use bytes;
  20. use integer;
  21. use Fcntl;
  22. use Errno;
  23. use Cwd;
  24. use IO::Handle;            # For flush()
  25.  
  26. sub absolute_path($) {
  27.     my($f) = @_;
  28.     my($c);
  29.  
  30.     return $f if ( $f =~ /^\// );
  31.     $c = cwd();
  32.     $c = '' if ( $c eq '/' );
  33.     return $c.'/'.$f;
  34. }
  35.  
  36. sub is_linux() {
  37.     return !!eval '{ '.
  38.     'use POSIX; '.
  39.     '($sysname, $nodename, $release, $version, $machine) = POSIX::uname(); '.
  40.     "return \$sysname eq \'Linux\'; }";
  41. }
  42.  
  43.  
  44. $is_linux = is_linux();
  45. if ( $is_linux ) {
  46.     # IOCTL numbers
  47.     $BLKRRPART    = 0x125f;
  48.     $BLKGETSIZE   = 0x1260;
  49. }
  50.  
  51. %opt = ();
  52. @args = ();
  53.  
  54. for $a ( @ARGV ) {
  55.     if ( $a =~ /^\-/ ) {
  56.     foreach $o ( split(//, substr($a,1)) ) {
  57.         $opt{$o} = 1;
  58.     }
  59.     } else {
  60.     push(@args, $a);
  61.     }
  62. }
  63.  
  64. ($file,$c,$h,$s) = @args;
  65. $c += 0;  $h += 0;  $s += 0;
  66.  
  67. $pentry = 1;
  68. $pentry = 2 if ( $opt{'2'} );
  69. $pentry = 3 if ( $opt{'3'} );
  70. $pentry = 4 if ( $opt{'4'} );
  71.  
  72. if ( $opt{'M'} ) {
  73.     # Specify size in megabytes, not in cylinders
  74.     $c = ($c*1024*2)/($h*$s);
  75. }
  76.  
  77. $is_open = 0;
  78.  
  79. if ( $c == 0 ) {
  80.     $len = 0;
  81.     if ( sysopen(OUTPUT, $file, O_RDWR, 0666) ) {
  82.     $is_open = 1;
  83.  
  84.     if ( (@filestat = stat(OUTPUT)) && S_ISREG($filestat[2]) ) {
  85.         $len = $filestat[7] >> 9;
  86.     } elsif ( $is_linux && S_ISBLK($filestat[2]) ) {
  87.         $blksize = pack("L!", 0);
  88.         if ( ioctl(OUTPUT, $BLKGETSIZE, $blksize) == 0 ) {
  89.         $len = unpack("L!", $blksize); # In 512-byte sectors!
  90.         }
  91.     }
  92.     }
  93.  
  94.     if ( !$len ) {
  95.     print STDERR "$0: $file: don't know how to determine the size of this device\n";
  96.     exit 1;
  97.     }
  98.  
  99.     $c = $len/($h*$s);
  100. }
  101.  
  102. if ( !$file || $c < 1 || $c > 1024 ||
  103.      $h < 1 || $h > 256 || $s < 1 || $s > 63 ) {
  104.     print STDERR "Usage: $0 [-doF4] file c h s (max: 1024 256 63)\n";
  105.     print STDERR "    -d    add DOSEMU header\n";
  106.     print STDERR "    -o    print filesystem offset to stdout\n";
  107.     print STDERR "    -F    format partition as FAT32\n";
  108.     print STDERR "    -M    \"c\" argument is megabytes, calculate cylinders\n";
  109.     print STDERR "    -4    use partition entry 4 (standard for zipdisks)\n";
  110.     exit 1;
  111. }
  112.  
  113. $cylsize = $h*$s*512;
  114.  
  115. if ( !$is_open ) {
  116.     sysopen(OUTPUT, $file, O_CREAT|O_RDWR|O_TRUNC, 0666)
  117.     or die "$0: Cannot open: $file\n";
  118. }
  119. binmode OUTPUT;
  120.  
  121. # Print out DOSEMU header, if requested
  122. if ( $opt{'d'} ) {
  123.     $emuhdr = "DOSEMU\0" . pack("VVVV", $h, $s, $c, 128);
  124.     $emuhdr .= "\0" x (128 - length($emuhdr));
  125.     print OUTPUT $emuhdr;
  126. }
  127.  
  128. # Print the MBR and partition table
  129. $mbr = '';
  130. while ( $line = <DATA> ) {
  131.     chomp $line;
  132.     foreach $byte ( split(/\s+/, $line) ) {
  133.     $mbr .= chr(hex($byte));
  134.     }
  135. }
  136. if ( length($mbr) > 446 ) {
  137.     die "$0: Bad MBR code\n";
  138. }
  139.  
  140. $mbr .= "\0" x (446 - length($mbr));
  141.  
  142. print OUTPUT $mbr;
  143.  
  144. # Print partition table
  145. $psize = $c*$h*$s-$s;
  146. $bhead   = ($h > 1) ? 1 : 0;
  147. $bsect   = 1;
  148. $bcyl    = ($h > 1) ? 0 : 1;
  149. $ehead   = $h-1;
  150. $esect   = $s + ((($c-1) & 0x300) >> 2);
  151. $ecyl    = ($c-1) & 0xff;
  152. if ( $psize > 65536 ) {
  153.     $fstype = 0x06;
  154. } else {
  155.     $fstype = 0x04;
  156. }
  157. for ( $i = 1 ; $i <= 4 ; $i++ ) {
  158.     if ( $i == $pentry ) {
  159.     print OUTPUT pack("CCCCCCCCVV", 0x80, $bhead, $bsect, $bcyl, $fstype,
  160.               $ehead, $esect, $ecyl, $s, $psize);
  161.     } else {
  162.     print OUTPUT "\0" x 16;
  163.     }
  164. }
  165. print OUTPUT "\x55\xaa";
  166.  
  167. # Output blank file
  168. $totalsize = $c*$h*$s;
  169. $tracks    = $c*$h;
  170.  
  171. $track = "\0" x (512*$s);
  172.  
  173. # Print fractional track
  174. print OUTPUT "\0" x (512 * ($s-1));
  175.  
  176. for ( $i = 1 ; $i < $tracks ; $i++ ) {
  177.     print OUTPUT $track;
  178. }
  179.  
  180. # Print mtools temp file
  181. $n = 0;
  182. while ( !defined($tmpdir) ) {
  183.     $tmpdir = "/tmp/mkdiskimage.$$.".($n++);
  184.     if ( !mkdir($tmpdir, 0700) ) {
  185.     die "$0: Failed to make temp directory: $tmpdir\n"
  186.         if ( $! != EEXIST );
  187.     undef $tmpdir;
  188.     }
  189. }
  190.  
  191. $cfgfile = $tmpdir.'/mtools.conf';
  192. $imglink = $tmpdir.'/disk.img';
  193. die "$0: Failed to create symlink $imglink\n"
  194.     if ( !symlink(absolute_path($file), $imglink) );
  195.  
  196. $header_size = ($opt{'d'} ? 128 : 0);
  197.  
  198. # Start of filesystem
  199. $offset = $s*512 + $header_size;
  200.  
  201. # Start of partition table entry
  202. $pstart = $header_size + 446 + 16*($pentry-1);
  203.  
  204. open(MCONFIG, "> ${cfgfile}") or die "$0: Cannot make mtools config\n";
  205. print MCONFIG "drive z:\n";
  206. print MCONFIG "file=\"${imglink}\"\n";
  207. print MCONFIG "cylinders=${c}\n";
  208. print MCONFIG "heads=${h}\n";
  209. print MCONFIG "sectors=${s}\n";
  210. print MCONFIG "offset=${offset}\n";
  211. print MCONFIG "mformat_only\n";
  212. close(MCONFIG);
  213.  
  214. # Output the filesystem offset to stdout if appropriate
  215. if ( $opt{'o'} ) {
  216.     print $offset, "\n";
  217. }
  218.  
  219. $ENV{'MTOOLSRC'} = $cfgfile;
  220. if ( $opt{'F'} ) {
  221.     system('mformat', '-F', 'z:');
  222. } else {
  223.     system('mformat', 'z:');
  224. }
  225.  
  226. # Clean up in /tmp
  227. unlink($cfgfile);
  228. unlink($imglink);
  229. rmdir($tmpdir);
  230.  
  231. # MTOOLS doesn't write the bsHiddenSecs field correctly
  232. seek(OUTPUT, $offset + 0x1c, 0);
  233. print OUTPUT pack("V", ($offset-$header_size)>>9);
  234.  
  235. # Set the partition type
  236. if ( $opt{'F'} ) {
  237.     $fstype = 0x0b;        # FAT32
  238. } else {
  239.     if ( $psize > 65536 ) {
  240.     $fstype = 0x06;        # FAT16 > 32MB
  241.     } else {
  242.     $fstype = 0x04;        # FAT16 <= 32MB
  243.     }
  244.     seek(OUTPUT, $offset + 0x36, 0);
  245.     read(OUTPUT, $fsname, 8);
  246.     
  247.     # FAT12: adjust partition type
  248.     if ( $fsname eq 'FAT12   ' ) {
  249.     $fstype = 0x01;        # FAT12
  250.     }
  251. }
  252. seek(OUTPUT, $pstart+4, 0);
  253. print OUTPUT pack("C", $fstype);
  254.  
  255. flush OUTPUT;
  256.  
  257. # Just in case this is a block device, try to flush the partition table
  258. if ( $is_linux ) {
  259.     ioctl(OUTPUT, $BLKRRPART, 0);
  260. };
  261.  
  262. exit 0;
  263. __END__
  264.